﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SegGen
{
   public class External_Archive_P:Population
    {

        

       public External_Archive_P(int numNucleotidesInCodon)
           : base(numNucleotidesInCodon)
        {
        }

        /// <summary>
        /// A hardness value H is given to each individual of the external archive . 
        /// This value is computed according to the number of individuals of (the current population) 
        /// that an element ∈ slightly dominates on both objective functions:
        /// </summary>
        /// <returns></returns>
            public override void calculateFitness( Population _currentPopulationPt )
        {
            // External archive P not = extArchP 
            double extArchP_C = 0;
            double extArchP_D = 0;
            int curDominatesCounter = 0;
    
            double curPopP_C = 0;
            double curPopP_D = 0;
            double sumExtArchDominates_H = 0;

            // only for first initialization
          //  bool isExtArchInit = false;

            // calculate Hardness for every individual in external archive P
            for (int ind1Index = 0; ind1Index < Individuals_List.Count; ind1Index++)
            {
                extArchP_C = Individuals_List.ElementAt(ind1Index).C;
                extArchP_D = Individuals_List.ElementAt(ind1Index).D;
                curDominatesCounter = 0;
               //_currentPopulation.
                
                for (int ind2Index = 0;  ind2Index < _currentPopulationPt.Individuals_List.Count ; ind2Index++)
                {
                    if (extArchP_C >= _currentPopulationPt.Individuals_List.ElementAt(ind2Index).C &&
                        extArchP_D >= _currentPopulationPt.Individuals_List.ElementAt(ind2Index).D )
                       
                    {
                        curDominatesCounter++;
                    }

                }// end ind2 for

                //if (curDominatesCounter == 0)
                //{
                //    Individuals_List.ElementAt(ind1Index).F = 0;
                //    continue;
                //}

                // if current population is not contain any individuals in initial state, then
                // all individuals from external archive is dominate 
                if (_currentPopulationPt.Individuals_List.Count == 0 /*&& isExtArchInit == false*/)
                {
                    curDominatesCounter = Individuals_List.Count;
                   // isExtArchInit = true;
                }
                // calculate hardness
                Individuals_List.ElementAt(ind1Index).H = (double)((double) curDominatesCounter / (double)(_currentPopulationPt.Individuals_List.Count + 1));
                // calculate fitness is inverse of its hardness value
                Individuals_List.ElementAt(ind1Index).F = (double) ((double) 1 / (double)(Individuals_List.ElementAt(ind1Index).H+1));
            }// end ind1 for


            /// calculate fitness for Current Population
            for (int curPopIndex = 0; curPopIndex < _currentPopulationPt.Individuals_List.Count; curPopIndex++)
            {
                curPopP_C = _currentPopulationPt.Individuals_List.ElementAt(curPopIndex).C;
                curPopP_D = _currentPopulationPt.Individuals_List.ElementAt(curPopIndex).D;
                sumExtArchDominates_H = 0;
                   
                    for (int extArchiveIndex = 0; extArchiveIndex < this.Individuals_List.Count; extArchiveIndex++)
                    {
                        if (curPopP_C <= this.Individuals_List.ElementAt(extArchiveIndex).C &&
                            curPopP_D <= this.Individuals_List.ElementAt(extArchiveIndex).D)
                        {
                            sumExtArchDominates_H += this.Individuals_List.ElementAt(extArchiveIndex).H;
                        }

                    }// end for
                    _currentPopulationPt.Individuals_List.ElementAt(curPopIndex).F =  (double)((double) 1 / (double)(1 + sumExtArchDominates_H));
            }// for


                // after calculating fitness we can calculate probability of selection for 
                // every individual

                //TODO: Probability of Selection
            //this.calculateProbabilityOfSelection();
        }


       
    /// <summary>
    ///  Extract the best solution from external archive
    /// </summary>
    /// <returns></returns>
         public override Individual ExtractionOfSolution()
        {
            double maxAgg      =  0;
            int    maxAggIndex = -1;
 
             // go to all individuals and find 
             // the best individual according to aggregation 
            for (int i = 0; i < Individuals_List.Count; i++ )
            {
                if(Individuals_List.ElementAt(i).Agg > maxAgg)
                {
                    maxAgg = Individuals_List.ElementAt(i).Agg;
                    maxAggIndex = i;
                }
            }

            if (maxAggIndex == -1) return null;

            return Individuals_List.ElementAt(maxAggIndex);
        }

    }


         
}
